#ifndef __VISUAL_H__
#define __VISUAL_H__

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "helper.h"
#include "cfd_utils.h"

/**********************************************************
		Data Structures
**********************************************************/
/**
 * Represents one particle in the domain
 */
struct particle
{
	double x; 		/**< x-coordinate */
	double y;		/**< y-coordinate */
	struct particle *next;	/**< Pointer to the next particle */
};

/**
 * Represents a pathline/streakline
 */
struct particle_line
{
	int length;			/**< Line length */
	struct particle *Particle;	/**< Pointer to the next particle */

};

struct particle_line *Particle_Lines;	/**< The Fluid particles */



/**********************************************************
		Functions
**********************************************************/

/**
 * Outputs U, V, and P to the output file specified by szProblem
 *
 * @param	xlength
 * @param	ylength
 * @param	imax
 * @param	jmax
 * @param	dx
 * @param	dy
 * @param	U
 * @param	V
 * @param	P
 * @param	Flag
 */
void output_uvp(const char *szProblem,
		double xlength,
                double ylength,
                int    imax,
                int    jmax,
		double dx,
		double dy,
                double **U,
                double **V,
                double **P,
                int **Flag
                );

/**
 * Writes the AVS field file
 *
 * @param	szProblem
 * @param	imax
 * @param	jmax
 * @param	xlength
 * @param	ylength
 * @param	nCount
 */
void write_fieldfile( const char *szProblem, int imax, int jmax,
                      double xlength, double ylength, int nCount );


/**
 * The memory space required for the particle lines will be dynamically allocated and the particle positions are entered in each particle line. Each particle line has an initial length 1 (see Figure 6 in worksheet 2).
 * The auxiliary element and the first real particle have the same coordinates.
 * A pointer will be returned to the allocated region.
 * The particles should be injected along the line segment with end points (x1, y1) and (x2,y2), the parameter N determining the number of particles equidistantly distributed along this line.
 *
 * @param 	N		The number of particles equidistantly distributed over the line specified by (x1,y1) and (x2,y2)
 * @param 	x1		The x-coordinate of the 1st point in the line used for particles/streaklines tracing
 * @param 	y1		The y-coordinate of the 1st point in the line used for particles/streaklines tracing
 * @param 	x2		The x-coordinate of the 2nd point in the line used for particles/streaklines tracing
 * @param 	y2		The y-coordinate of the 2nd point in the line used for particles/streaklines tracing
 *
 * @return A pointer to the allocated particles line
 */
struct particle_line *set_particle( int N,
				    double x1,
				    double y1,
				    double x2,
				    double y2
				    );


/**
 * The particle positions at time step tn held in Particle Lines (an array of particle line) are updated, according to (B), to the particle positions of time step t_n + 1. The particles that, as a result, leave the domain R = [0; imax * dx] x [0; jmax * dy] or run into the obstacle cells are deleted from the list, and the memory occupied by these particles is returned using the free function.
 * @param	Particle_Lines	The array storing the traced particles
 * @param	N		The number of particles equidistantly distributed over the line specified by (x1,y1) and (x2,y2)
 * @param	dt		The time step used for solving the problem
 * @param	dx		cell length in x-direction
 * @param	dy		cell length in y-direction
 * @param	imax		Number of interior cells in x-direction
 * @param	jmax		Number of interior cells in y-direction
 * @param	U		The velocity in x-direction
 * @param	V		The velocity in y-direction
 * @param	Flag		The fluid-obstacle flags matrix
 */
void move_particle( struct particle_line *Particle_Lines,
		    int N,
		    double dt,
		    double dx,
		    double dy,
		    int imax,
		    int jmax,
		    double **U,
		    double **V,
		    int **Flag
		    );


/**
 * The particles specified in set particles are injected along the given line segment by inserting a particle in the beginning of the list in each particle line from Particle Lines, with the position specified in the auxiliary element. Besides, the necessary storage must be allocated for the new particle.
 * @param	Particle_Lines	The array storing the traced particles
 * @param	N		The number of particles equidistantly distributed over the line specified by (x1,y1) and (x2,y2)
 */
void insert_particles(	struct particle_line *Particle_Lines, int N);



/**
 * The particle positions contained in Particle Lines are written to the file specified in the input parameter outputfile
 * @param	Particle_Lines	The array storing the traced particles
 * @param	N		The number of particles equidistantly distributed over the line specified by (x1,y1) and (x2,y2)
 * @param	partmax		The maximum number of particles to be visualized
 * @param	outputfile	The name of the output file (name without extension)
 */
void write_particles(	struct particle_line *Particle_Lines,
			int N,
			int partmax,
			char *outputfile
			);


/**
 * This routine calculates the current positions of the particles to be traced at each time step using move particles and overwrites their old positions in Particle Lines.
 * The current particle positions are appended, at time intervals dt path, to the output file specified by the input parameter outputfile using write particles. The header of this output file contains the quantities xlength, ylength and N.
 * @param	Particle_Lines	The array storing the traced particles
 * @param	N		The number of particles equidistantly distributed over the line specified by (x1,y1) and (x2,y2)
 * @param	outputfile	The name of the output file (name without extension)
 * @param	dt_path		The time step used to output the path lines
 * @param	t
 * @param	dx
 * @param	dy
 * @param	dt
 * @param	imax
 * @param	jmax
 * @param	U
 * @param	V
 * @param	Flag		The fluid-obstacle flags matrix
 */
void pathlines(	struct particle_line *Particle_Lines,
		int N,
		char *outputfile,
		double dt_path,
		double t,
		double dx,
		double dy,
		double dt,
		int imax,
		int jmax,
		double **U,
		double **V,
		int **Flag
		);


/**
 * At each time step, the current particle positions are computed with the help of move particle and their old positions in Particle Lines are overwritten.
 * At time intervals dt insert, particles are injected with the help of the function insert particles, and at time intervals dt streak the current particle positions are written by the function write particles to the file specified in the input parameter outputfile.
 * This file contains the quantities xlength, and ylength.
 * @param	Particle_Lines
 * @param	N
 * @param	dt_inject
 * @param	dt_streak
 * @param	t
 * @param	dx
 * @param	dy
 * @param	dt
 * @param	imax
 * @param	jmax
 * @param	U
 * @param	V
 * @param	outputfile
 * @param	Flag		The fluid-obstacle flags matrix
 */
void streaklines (
		struct particle_line *Particle_Lines,
		int N,
		double dt_inject,
		double dt_streak,
		double t,
		double dx,
		double dy,
		double dt,
		int imax,
		int jmax,
		double **U,
		double **V,
		char *outputfile,
		int **Flag
		);


/**
 * Calculates the vorticity (Psi) and the stream function (Zeta)
 *
 * @param	dx
 * @param	dy
 * @param	imax
 * @param	jmax
 * @param	U
 * @param	V
 * @param	Psi
 * @param	Zeta
 * @param	Flag
 */
void calculate_psi_zeta (
			double dx,
			double dy,
			int imax,
			int jmax,
			double **U,
			double **V,
			double **Psi,
			double **Zeta,
			int **Flag
			);
/**
 * Outputs the current locations of the fluid particles into the outputfile.
 *
 * @param	Particle_Lines
 * @param	outputfile
 * @param	N
 * @param	npart
 * @param	t
 * @param	xlength
 * @param	xlength
 * @param	ylength
 * @param	dt_visual
 *
 */
void trace_fluid(
		struct particle_line *Particle_Lines,
		char 	*outputfile,
		int 	N,
		int 	npart,
		double 	t,
		int 	xlength,
		int 	ylenght,
		double 	dt_visual
		);
#endif
